package com.hhy.lombok.processor;

import com.hhy.lombok.annotation.NoArgsConstructor;
import com.hhy.lombok.utils.JCUtils;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.TypeTag;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeTranslator;
import com.sun.tools.javac.util.List;

import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import java.lang.annotation.Annotation;
import java.util.Set;

import static com.hhy.lombok.constant.Constant.*;
import static com.sun.tools.javac.util.List.nil;


@SupportedAnnotationTypes("com.hhy.lombok.annotation.NoArgsConstructor")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class NoArgsConstructorProcessor extends BaseProcessor {

    @Override
    public void doProcess(Element element) {
        //获取当前元素的JCTree对象
        JCTree jcTree = trees.getTree(element);
        jcTree.accept(new TreeTranslator() {
            @Override
            public void visitClassDef(JCTree.JCClassDecl jcClass) {
                treeMaker.at(jcClass.pos);
                //添加无参构造方法
                if (!hasNoArgsConstructor(jcClass)) {
                    jcClass.defs = jcClass.defs.append(
                            createNoArgsConstructor()
                    );
                    log.log(jcClass, "generated no args constructor");
                }
            }
        });
    }

    /**
     * 创建无参数构造方法
     *
     * @return 无参构造方法语法树节点
     */
    private JCTree.JCMethodDecl createNoArgsConstructor() {
        return JCUtils.createMethod(treeMaker,
                names.fromString(CONSTRUCTOR_NAME),
                treeMaker.TypeIdent(TypeTag.VOID),
                nil(),
                nil(),
                JCUtils.createBlock(treeMaker, List.nil()),
                Flags.PUBLIC
        );
    }

    /**
     * 判断是否存在无参构造方法
     *
     * @param jcClass 类的语法树节点     * @return 是否存在
     */
    private static boolean hasNoArgsConstructor(JCTree.JCClassDecl jcClass) {
        for (JCTree jcTree : jcClass.defs) {
            if (jcTree.getKind().equals(JCTree.Kind.METHOD)) {
                JCTree.JCMethodDecl jcMethod = (JCTree.JCMethodDecl) jcTree;
                if (CONSTRUCTOR_NAME.equals(jcMethod.name.toString()) && jcMethod.params.isEmpty()) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    protected Class<? extends Annotation> getNeedToHandleAnnotation() {
        return NoArgsConstructor.class;
    }
}